home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Online / HBBS / Source / Node / NodeLibrary / HBBSNode.c < prev    next >
C/C++ Source or Header  |  1997-09-04  |  51KB  |  1,745 lines

  1. #define HBBSNODELIB
  2. #define MAIN
  3.  
  4. #include <ctype.h>
  5. #include <time.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include <exec/exec.h>
  11. #include <exec/types.h>
  12.  
  13. #include <dos/dos.h>
  14. #include <dos/dostags.h>
  15.  
  16. #include <libraries/reqtools.h>
  17.  
  18. #include <intuition/intuition.h>
  19.  
  20. #include <devices/console.h>
  21. #include <devices/conunit.h>
  22.  
  23. #include <devices/serial.h>
  24. #include <hardware/cia.h>
  25.  
  26. #include <graphics/gfxbase.h>
  27. #include <graphics/scale.h>
  28.  
  29.  
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32. #include <clib/alib_protos.h>
  33. #include <clib/reqtools_protos.h>
  34. #include <clib/graphics_protos.h>
  35.  
  36. #include <clib/intuition_protos.h>
  37. #include <clib/console_protos.h>
  38. #include <clib/graphics_protos.h>
  39.  
  40. #include <pragmas/exec_pragmas.h>
  41. #include <pragmas/graphics_pragmas.h>
  42. #include <pragmas/dos_pragmas.h>
  43. #include <pragmas/reqtools.h>
  44. #include <pragmas/intuition_pragmas.h>
  45.  
  46.  
  47.  
  48. #include <hbbs/release.h>
  49. #include <hbbs/types.h>
  50. #include <hbbs/errors.h>
  51. #include <hbbs/defines.h>
  52. #include <hbbs/structures.h>
  53. #include <hbbs/strings.h>
  54. #include <hbbs/files.h>
  55. #include <hbbs/access.h>
  56.  
  57. #include <HBBS/Hbbscommon_protos.h>
  58. #ifdef __SASC
  59. #include <HBBS/hbbscommon_pragmas_sas.h>
  60. #else
  61. #include <HBBS/hbbscommon_pragmas_stc.h>
  62. #endif
  63.  
  64. #include <HBBS/Hbbsnode_protos.h>
  65. #ifdef __SASC
  66. #include <HBBS/Hbbsnode_pragmas_sas.h>
  67. #else
  68. #include <HBBS/Hbbsnode_pragmas_stc.h>
  69. #endif
  70.  
  71. #define ClrSignal(s)  SetSignal(0,s)
  72.  
  73. char *versionstr="$VER: HBBSNode.library "RELEASE_STR;
  74.  
  75.  
  76. // needed libs..
  77.  
  78. struct DosLibrary *DOSBase=NULL;
  79. struct GfxBase *GfxBase=NULL;
  80. struct ExecBase *SysBase=NULL;
  81. struct ReqToolsBase *ReqToolsBase=NULL;
  82. struct Library *HBBSCommonBase=NULL;
  83. struct IntuitionBase *IntuitionBase = NULL;
  84.  
  85. struct BBSGlobalData *BBSGlobal=NULL;
  86. struct NodeData *N_ND=NULL;
  87.  
  88. struct DoorData C_DOOR; // current door (if active of course!)
  89.  
  90. V_BOOL DoorOK=FALSE;
  91.  
  92. // * SOME FORWARD DEFINES..
  93.  
  94. LONG __asm __saveds LIBHBBS_TimeOnline( void );
  95. LONG __asm __saveds LIBHBBS_TimeLeft( void );
  96.  
  97. void DoorStatus(V_BIGNUM status)
  98. {
  99.   struct DoorActivityMsg *DMsg;
  100.  
  101.   // memory will be free'd by NODE program (if node is alive of course!)
  102.   if (DMsg=(struct DoorActivityMsg *)AllocVec(sizeof(struct DoorActivityMsg),MEMF_PUBLIC))
  103.   {
  104.     DMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  105.     DMsg->message.mn_ReplyPort=NULL;  // must set to null!
  106.     DMsg->message.mn_Length=sizeof(struct DoorActivityMsg);
  107.     DMsg->MsgType=mtype_DOORACTIVITY;
  108.     DMsg->Status=status;
  109.     SendMessage((struct Message*)DMsg,N_ND->PortName);
  110.   }
  111. }
  112.  
  113. BOOL SendStartDoorMsg( void )
  114. {
  115.   struct DoorActivityMsg *DMsg;
  116.   BOOL retval=FALSE;
  117.  
  118.   if (DMsg=AllocVec(sizeof(struct DoorActivityMsg ),MEMF_PUBLIC))
  119.   {
  120.     DMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  121.     DMsg->message.mn_ReplyPort=C_DOOR.ReplyPort;
  122.     DMsg->message.mn_Length=sizeof(struct DoorActivityMsg);
  123.     DMsg->MsgType=mtype_DOORACTIVITY;
  124.     DMsg->Status=1;
  125.     if (SendMessage((struct Message*)DMsg,N_ND->DoorStartPortName)) retval=TRUE;
  126.     FreeVec(DMsg);
  127.   }
  128.   return(retval);
  129. }
  130.  
  131.  
  132. BOOL __asm __saveds LIBHBBS_InitNode(register __d0 int N_NodeNum)
  133. {
  134.   SysBase = *(struct ExecBase **) 4L;
  135.   if (DOSBase = (struct DosLibrary *) OpenLibrary (DOSNAME, 0))
  136.   {
  137.     if (GfxBase = (struct GfxBase *) OpenLibrary (GRAPHICSNAME, 0))
  138.     {
  139.       if (IntuitionBase = (struct IntuitionBase * )OpenLibrary((UBYTE *)"intuition.library" , 37))
  140.       {
  141.         if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary (REQTOOLSNAME, REQTOOLSVERSION))
  142.         {
  143.           if (HBBSCommonBase = OpenLibrary("HBBSCommon.library",0))
  144.           {
  145.             if (BBSGlobal=HBBS_GimmeBBS())
  146.             {
  147.               if (N_ND=HBBS_NodeDataPtr(N_NodeNum))
  148.               {
  149.                 return(TRUE);
  150.               }
  151.             }
  152.           }
  153.         }
  154.       }
  155.     }
  156.   }
  157.   return(FALSE);
  158. }
  159.  
  160. void __asm __saveds LIBHBBS_CleanUpNode( void )
  161. {
  162.   if (HBBSCommonBase)
  163.   {
  164. //    if (N_ND) HBBS_ResetNodeData(N_ND); // reset node variables
  165.     CloseLibrary (HBBSCommonBase);
  166.   }
  167.   if (ReqToolsBase)   CloseLibrary ((struct Library *)ReqToolsBase);
  168.   if (GfxBase)        CloseLibrary ((struct Library *) GfxBase);
  169.   if (IntuitionBase ) CloseLibrary( ( struct Library * )IntuitionBase );
  170.   if (DOSBase)        CloseLibrary ((struct Library *) DOSBase);
  171. }
  172.  
  173. BOOL __asm __saveds LIBHBBS_InitDoor( register __d0 int N_NodeNum, register __a0 char *name)
  174. {
  175.   if (LIBHBBS_InitNode(N_NodeNum))
  176.   {
  177.     C_DOOR.node.ln_Name=name;
  178.  
  179.     sprintf(C_DOOR.DoorPortName,"HBBS_Node_%ldDP%ld",N_NodeNum,N_ND->DoorsRunning+1); // we increment door number below..
  180.  
  181.     if (C_DOOR.DoorPort=CreatePort(C_DOOR.DoorPortName,0)) // named port
  182.     {
  183.       if (C_DOOR.ReplyPort=CreateMsgPort()) // unnamed port
  184.       {
  185.         // these must be updated at the same time as we don't want another program referencing
  186.         // ActiveDoor AND the door list and it not being correct now do we ? :-)
  187.  
  188.         Forbid();
  189.         N_ND->ActiveDoor=&C_DOOR;
  190.         AddHead(N_ND->DoorList,(struct Node*)&C_DOOR);
  191.         N_ND->DoorsRunning++;
  192.         Permit();
  193.  
  194.         // tell the NODE the door is running OK (if the node does not get a door OK message)
  195.         // within 15 seconds then it timesout! (unlike /X which locks up!!)
  196.  
  197.         if (SendStartDoorMsg())
  198.         {
  199.           DoorStatus(DMSG_DOORSTARTED);
  200.           // set the internal library's flag (used when we close the door down to free mem!
  201.           DoorOK=TRUE;
  202.           return(TRUE);
  203.         }
  204.  
  205.       }
  206.       else DeletePort(C_DOOR.DoorPort);
  207.     }
  208.   }
  209.   return(FALSE);
  210. }
  211.  
  212. void __asm __saveds LIBHBBS_CleanUpDoor( void )
  213. {
  214.   if (DoorOK)
  215.   {
  216.     DeleteMsgPort(C_DOOR.ReplyPort); // unnnamed port
  217.     DeletePort(C_DOOR.DoorPort);     // named port
  218.     Forbid();
  219.     // remove ourself from the doorlist
  220.  
  221.     RemHead(N_ND->DoorList);
  222.  
  223.     N_ND->DoorsRunning--;
  224.  
  225.     // set the active door to the door that called us (if we were spawned by another door)
  226.     // if not, set activedoor to null
  227.  
  228.     if (N_ND->DoorList->lh_Head->ln_Succ) // more doors ?
  229.     {
  230.       N_ND->ActiveDoor=(struct DoorData *)N_ND->DoorList->lh_Head;
  231.     }
  232.     else N_ND->ActiveDoor=NULL;
  233.  
  234.     Permit();
  235.  
  236.  
  237.     // tell the node that we've finished!
  238.     DoorStatus(DMSG_DOORFINISHED);
  239.  
  240.   }
  241.   LIBHBBS_CleanUpNode();
  242. }
  243. void  __asm __saveds LIBConWriteData(register __a0 UBYTE *data,register __d0 ULONG length)
  244. {
  245.   if (N_ND->ConOK && data && length>=0)
  246.   {
  247.     N_ND->ConWrite->io_Command  = CMD_WRITE;
  248.     N_ND->ConWrite->io_Data     = data;
  249.     N_ND->ConWrite->io_Length   = length;
  250.  
  251.     DoIO((struct IORequest *)N_ND->ConWrite);
  252.   }
  253. }
  254.  
  255. void  __asm __saveds LIBConWriteStr(register __a0 UBYTE *data)
  256. {
  257.   if (N_ND->ConOK && data)
  258.   {
  259.     N_ND->ConWrite->io_Command  = CMD_WRITE;
  260.     N_ND->ConWrite->io_Data     = data;
  261.     N_ND->ConWrite->io_Length   = -1;
  262.  
  263.     DoIO((struct IORequest *)N_ND->ConWrite);
  264.   }
  265. }
  266.  
  267. void  __asm __saveds LIBAbortConRead( void )
  268. {
  269.   if (N_ND->ConWaiting)
  270.   {
  271.     if (!CheckIO((struct IORequest*)N_ND->ConRead))
  272.     {
  273.       AbortIO((struct IORequest*)N_ND->ConRead);
  274.       WaitIO((struct IORequest*)N_ND->ConRead);
  275.     }
  276.     N_ND->ConWaiting=FALSE;
  277.   }
  278. }
  279.  
  280. void  __asm __saveds LIBSendConReadData( void )
  281. {
  282.   if (N_ND->ConWaiting) LIBAbortConRead();
  283.   N_ND->ConRead->io_Command  = CMD_READ;
  284.   N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  285.   N_ND->ConRead->io_Length   = N_ND->ConBufferLen;
  286.  
  287.   ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  288.   SendIO((struct IORequest*)N_ND->ConRead);
  289.   N_ND->ConWaiting=TRUE;
  290. }
  291.  
  292. void  __asm __saveds LIBConReadData(register __d0 ULONG Length ) // make DAMN sure that length is NEVER more that the buffer size!
  293. {
  294.   if (N_ND->ConWaiting) LIBAbortConRead();
  295.   N_ND->ConRead->io_Command  = CMD_READ;
  296.   N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  297.   N_ND->ConRead->io_Length   = Length;
  298.  
  299.   ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  300.   SendIO((struct IORequest*)N_ND->ConRead);
  301.   N_ND->ConWaiting=TRUE;
  302. }
  303.  
  304. void  __asm __saveds LIBConWaitData( void )
  305. {
  306.   if (!N_ND->ConWaiting) LIBSendConReadData();
  307.   WaitIO((struct IORequest*)N_ND->ConRead);
  308.   N_ND->ConWaiting=FALSE;
  309.   N_ND->ConBytes=N_ND->ConRead->io_Actual;
  310. }
  311.  
  312. // aborts an iorequest that has been sent
  313.  
  314. void __asm __saveds LIBAbortSerRead( void )
  315. {
  316.   if (N_ND->SerWaiting)
  317.   {
  318.     if (!CheckIO((struct IORequest*)N_ND->SerRead))
  319.     {
  320.       AbortIO((struct IORequest*)N_ND->SerRead);
  321.     }
  322.     WaitIO((struct IORequest*)N_ND->SerRead); // to tidy up..
  323.     N_ND->SerWaiting=FALSE;
  324.   }
  325. }
  326.  
  327. // SendIO()'s a request to read 1 bye
  328.  
  329. void __asm __saveds LIBSendSerReadData( void )
  330. {
  331.   N_ND->SerRead->IOSer.io_Command  = CMD_READ;
  332.   N_ND->SerRead->IOSer.io_Data     = (APTR)N_ND->SerBuffer;
  333.   N_ND->SerRead->IOSer.io_Length   = 1;
  334.  
  335.   ClrSignal(1L << N_ND->SerPort->mp_SigBit);
  336.   SendIO((struct IORequest*)N_ND->SerRead);
  337.   N_ND->SerWaiting=TRUE;
  338. }
  339.  
  340. void __asm __saveds LIBSerWaitData( void )
  341. {
  342.   if (!N_ND->SerWaiting) LIBSendSerReadData();
  343.   WaitIO((struct IORequest*)N_ND->SerRead);
  344.   N_ND->SerBytes=N_ND->SerRead->IOSer.io_Actual;
  345.   N_ND->SerWaiting=FALSE;
  346. }
  347.  
  348. // SendIO()'s a request to read a block of data
  349.  
  350. void __asm __saveds LIBSendSerReadBlock(register __a0 UBYTE *data,register __d0 ULONG length )
  351. {
  352.   LIBAbortSerRead(); // *C* not sure about this one..  might slowdown throughput..
  353.  
  354.   N_ND->SerRead->IOSer.io_Command  = CMD_READ;
  355.   N_ND->SerRead->IOSer.io_Data     = (APTR)data;
  356.   N_ND->SerRead->IOSer.io_Length   = length;
  357.  
  358.   ClrSignal(1L << N_ND->SerPort->mp_SigBit);
  359.   SendIO((struct IORequest*)N_ND->SerRead);
  360.   N_ND->SerWaiting=TRUE;
  361. }
  362.  
  363. // DioIO()'s a request to read a block of data
  364.  
  365. void __asm __saveds LIBWaitSerReadBlock(register __a0 UBYTE *data,register __d0 ULONG length )
  366. {
  367.   LIBSendSerReadBlock(data,length);
  368.   LIBSerWaitData();
  369. }
  370.  
  371. // DoIO()'s a Query!
  372.  
  373. ULONG __asm __saveds LIBSerQueryData( void )
  374. {
  375.   N_ND->SerWrite->IOSer.io_Command  = SDCMD_QUERY;
  376.   DoIO((struct IORequest*)N_ND->SerWrite);
  377.   return(N_ND->SerWrite->IOSer.io_Actual);
  378. }
  379.  
  380. V_BOOL __asm __saveds LIBCarrierLost( void )
  381. {
  382.   if (N_ND->LoginType==LOGIN_REMOTE && !N_ND->NodeDevice.NullModemCable)
  383.   {
  384.     if (N_ND->NodeSettings.UseDevice)
  385.     {
  386.       LIBSerQueryData();
  387.       return((N_ND->SerWrite->io_Status & 1L << CIAB_COMCD) ? (V_BOOL)TRUE : (V_BOOL)FALSE);
  388.     }
  389.   }
  390.   return((V_BOOL)FALSE);
  391. }
  392.  
  393. // writes a block of data to the serial port, checking for a timeout
  394. // (specified in seconds,micros) and returns FALSE if a timeout occured before all
  395. // the data has been sent, or there was a memory error.
  396.  
  397. BOOL __asm __saveds LIBSerWriteDataWithTimeout(register __a0 UBYTE *data,register __d0 ULONG length,register __d1 ULONG Seconds,register __d2 ULONG Micros)
  398. {
  399.   BOOL retval=FALSE;
  400.   struct TimerData *TD;
  401.  
  402.   if (TD=SubmitTimer(N_ND->NodeTimer,Seconds,Micros))
  403.   {
  404.     if (data && length>0)
  405.     {
  406.       LIBAbortSerRead();
  407.       N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  408.       N_ND->SerWrite->IOSer.io_Data     = data;
  409.       N_ND->SerWrite->IOSer.io_Length   = length;
  410.  
  411.       SendIO((struct IORequest *)N_ND->SerWrite);
  412.  
  413.       // ok, wait for the timer or serial device to tell us sommat..
  414.       Wait (DEF_TIMERSIG | DEF_SERSIG);
  415.  
  416.       // ok sommat hapenned. lets check the timer..
  417.       if (CheckTimer(N_ND->NodeTimer,TD))
  418.       {
  419.         // yup, timeout occured, so abort the serial write request..
  420.         AbortIO((struct IORequest *)N_ND->SerWrite);
  421.         TD=NULL;
  422.       }
  423.       else
  424.       {
  425.         // timer not done yet, so it must be the serial port that finished..
  426.         retval=TRUE;
  427.       }
  428.       // and then tidy up..
  429.       WaitIO((struct IORequest *)N_ND->SerWrite);
  430.     }
  431.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  432.   }
  433.   return(retval);
  434. }
  435.  
  436. // writes a block of data to the serial port without checking for a timeout..
  437.  
  438. void __asm __saveds LIBSerWriteData(register __a0 UBYTE *data,register __d0 ULONG length)
  439. {
  440.   if (data && length>0)
  441.   {
  442.     LIBAbortSerRead();
  443.     N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  444.     N_ND->SerWrite->IOSer.io_Data     = data;
  445.     N_ND->SerWrite->IOSer.io_Length   = length;
  446.  
  447.     DoIO((struct IORequest *)N_ND->SerWrite);
  448.   }
  449. }
  450.  
  451. BOOL __asm __saveds LIBSerWriteStrWithTimeout(register __a0 UBYTE *str,register __d0 ULONG Seconds,register __d1 ULONG Micros)
  452. {
  453.   BOOL retval=FALSE;
  454.   struct TimerData *TD;
  455.  
  456.   if (TD=SubmitTimer(N_ND->NodeTimer,Seconds,Micros))
  457.   {
  458.     if (str && str[0])  // str valid pointer ? and does it contain data ??
  459.     {
  460.       LIBAbortSerRead();
  461.       N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  462.       N_ND->SerWrite->IOSer.io_Data     = str;
  463.       N_ND->SerWrite->IOSer.io_Length   = strlen(str);
  464.  
  465.       ClrSignal(DEF_TIMERSIG | DEF_SERSIG);
  466.  
  467.       SendIO((struct IORequest *)N_ND->SerWrite);
  468.  
  469.       // ok, wait for the timer or serial device to tell us sommat..
  470.       Wait (DEF_TIMERSIG | DEF_SERSIG);
  471.  
  472.       // ok sommat hapenned. lets check the timer..
  473.       if (CheckTimer(N_ND->NodeTimer,TD))
  474.       {
  475.         TD=NULL;
  476.         // yup, timeout occured, so abort the serial write request..
  477.         AbortIO((struct IORequest *)N_ND->SerWrite);
  478.       }
  479.       else
  480.       {
  481.         // timer not done yet, so it must be the serial port that finished..
  482.         retval=TRUE;
  483.         // and then tidy up..
  484.       }
  485.       WaitIO((struct IORequest *)N_ND->SerWrite);
  486.     }
  487.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  488.   }
  489.   return(retval);
  490. }
  491.  
  492. // writes a string to the serial device..
  493.  
  494. void __asm __saveds LIBSerWriteStr(register __a0 UBYTE *str)
  495. {
  496.   if (str && str[0])   // str valid pointer ? and does it contain data ??
  497.   {
  498.     LIBAbortSerRead();
  499.     N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  500.     N_ND->SerWrite->IOSer.io_Data     = str;
  501.     N_ND->SerWrite->IOSer.io_Length   = strlen(str);
  502.  
  503.     // hehe LamiExpress sets io_Length to strlen(str).. LAME! ;-)
  504.     // if they read the docs they might see that setting io_Length to -1
  505.     // makes the device output the contents of io_Data until it encounters
  506.     // a null terminator! :-)
  507.  
  508.     // ah but perhaps wih good reason !?!
  509.     // the C= serial.device outputs the /0 and then stops instead of
  510.     // stopping without outputting the /0
  511.  
  512.     DoIO((struct IORequest *)N_ND->SerWrite);
  513.   }
  514. }
  515.  
  516.  
  517. // writes a string to the serial device.. but replaces ~'s with delays!
  518.  
  519. void __asm __saveds LIBSerDelayWriteStr(register __a0 UBYTE *str)
  520. {
  521.   int loop=0;
  522.   if (str && str[0])   // str valid pointer ? and does it contain data ??
  523.   {
  524.     LIBAbortSerRead();
  525.  
  526.     while (str[loop])
  527.     {
  528.       if (str[loop]=='~')
  529.       {
  530.         Delay(N_ND->NodeDevice.TildeDelay);
  531.       }
  532.       else
  533.       {
  534.         N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  535.         N_ND->SerWrite->IOSer.io_Data     = &str[loop];
  536.         N_ND->SerWrite->IOSer.io_Length   = 1;
  537.         DoIO((struct IORequest *)N_ND->SerWrite);
  538.       }
  539.       loop++;
  540.     }
  541.  
  542.   }
  543. }
  544.  
  545.  
  546.  
  547.  
  548.  
  549. // writes a char to the serial device..
  550.  
  551. void __asm __saveds LIBSerWriteChar(register __d0 UBYTE c)
  552. {
  553.   char ch=c;
  554.  
  555.   LIBAbortSerRead();
  556.   N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  557.   N_ND->SerWrite->IOSer.io_Data     = &ch;
  558.   N_ND->SerWrite->IOSer.io_Length   = 1;
  559.   DoIO((struct IORequest *)N_ND->SerWrite);
  560. }
  561.  
  562. void  __asm __saveds LIBPutText(register __a0 UBYTE *str)
  563. {
  564.   // generic routine for all string output, this determines wether or not
  565.   // to write to the console or serial ports..
  566.  
  567.   if (str && str[0])
  568.   {
  569.     if (N_ND->ConOK)
  570.     {
  571.       N_ND->ConWrite->io_Command  = CMD_WRITE;
  572.       N_ND->ConWrite->io_Data     = str;
  573.       N_ND->ConWrite->io_Length   = -1;
  574.       DoIO((struct IORequest *)N_ND->ConWrite);
  575.     }
  576.     if ((N_ND->LoginType==LOGIN_REMOTE) && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL)))
  577.     {
  578.       LIBAbortSerRead();
  579.       N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  580.       N_ND->SerWrite->IOSer.io_Data     = str;
  581.       N_ND->SerWrite->IOSer.io_Length   = strlen(str);
  582.       DoIO((struct IORequest *)N_ND->SerWrite);
  583.     }
  584.   }
  585. }
  586.  
  587. void  __asm __saveds LIBPutData(register __a0 UBYTE *data,register __d0 ULONG Length)
  588. {
  589.   // generic routine for all tring output, this determines wether or not
  590.   // to write to the console or serial ports..
  591.  
  592.   if (N_ND->ConOK) LIBConWriteData(data,Length);
  593.   if ((N_ND->LoginType==LOGIN_REMOTE)  && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL))) LIBSerWriteData(data,Length);
  594. }
  595.  
  596. void  __asm __saveds LIBPutChar(register __d0 UBYTE ch)
  597. {
  598.   char c=ch;
  599.   // generic routine for all tring output, this determines wether or not
  600.   // to write to the console or serial ports..
  601.   if (N_ND->ConOK) LIBConWriteData(&c,1);
  602.   if ((N_ND->LoginType==LOGIN_REMOTE) && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL))) LIBSerWriteData(&c,1);
  603. }
  604.  
  605. void  __asm __saveds LIBPutConText(register __a0 UBYTE *str)
  606. {
  607.   // generic routine for all tring output, this determines wether or not
  608.   // to write to the console or serial ports..
  609.  
  610.   if (N_ND->ConOK) LIBConWriteStr(str);
  611. }
  612.  
  613. void  __asm __saveds LIBPutConData(register __a0 UBYTE *data,register __d0 ULONG Length)
  614. {
  615.   // generic routine for all tring output, this determines wether or not
  616.   // to write to the console or serial ports..
  617.  
  618.   if (N_ND->ConOK) LIBConWriteData(data,Length);
  619. }
  620.  
  621. void  __asm __saveds LIBPutConChar(register __d0 UBYTE ch)
  622. {
  623.   char c=ch;
  624.   // generic routine for all tring output, this determines wether or not
  625.   // to write to the console or serial ports..
  626.   if (N_ND->ConOK) LIBConWriteData(&c,1);
  627. }
  628.  
  629. ULONG __asm __saveds LIBSetupConSerSigs( void )
  630. {
  631.   N_ND->ConSig=0L;
  632.   N_ND->ConWinSig=0L;
  633.   if (N_ND->ConOK)
  634.   {
  635.     if (N_ND->ConWaiting) N_ND->ConSig=DEF_CONSIG;
  636.     N_ND->ConWinSig=DEF_CONWINSIG;
  637.   }
  638.  
  639.   // only check serial if remote login.. OR if no-one's connected yet..
  640.  
  641.   if (N_ND->LoginType !=LOGIN_LOCAL && N_ND->SerOK && N_ND->SerWaiting)
  642.     N_ND->SerSig=DEF_SERSIG;
  643.   else
  644.     N_ND->SerSig=0;
  645.  
  646.   return(N_ND->SerSig | N_ND->ConSig);
  647. }
  648.  
  649. ULONG __asm __saveds LIBHandleConSigs(register __d0 ULONG ReturnedSigs)
  650. {
  651.   // a calling routine should call this until it returns false
  652.   // this is cos you might get two signals at the same time
  653.   // and you don't want to miss anything!
  654.  
  655.   if (ReturnedSigs & N_ND->ConSig && N_ND->ConOK && N_ND->ConWaiting)
  656.   {
  657.     LIBConWaitData();
  658.     N_ND->IBuffer=N_ND->ConBuffer;
  659.     N_ND->IBytes=N_ND->ConBytes;
  660.     return(TRUE);
  661.   }
  662.   return(FALSE);
  663. }
  664.  
  665. ULONG __asm __saveds LIBHandleSerSigs(register __d0 ULONG ReturnedSigs)
  666. {
  667.   // a calling routine should call this until it returns false
  668.   // this is cos you might get two signals at the same time
  669.   // and you don't want to miss anything!
  670.  
  671.  
  672.   if (ReturnedSigs & N_ND->SerSig && N_ND->SerOK && N_ND->SerWaiting)
  673.   {
  674.     LIBSerWaitData();
  675.     N_ND->IBuffer=N_ND->SerBuffer;
  676.     N_ND->IBytes=N_ND->SerBytes;
  677.     return(TRUE);
  678.   }
  679.   return(FALSE);
  680. }
  681.  
  682. ULONG __asm __saveds LIBHandleConSerSigs(register __d0 ULONG ReturnedSigs)
  683. {
  684.   // a calling routine should call this until it returns false
  685.   // this is cos you might get two signals at the same time
  686.   // and you don't want to miss anything!
  687.  
  688.   if (LIBHandleConSigs(ReturnedSigs) || LIBHandleSerSigs(ReturnedSigs))
  689.   {
  690.     return(TRUE);
  691.   }
  692.   else return(FALSE);
  693.  
  694. /*  if (ReturnedSigs & N_ND->ConSig && N_ND->ConOK && N_ND->ConWaiting)
  695.   {
  696.     LIBConWaitData();
  697.     N_ND->IBuffer=N_ND->ConBuffer;
  698.     N_ND->IBytes=N_ND->ConBytes;
  699.     return(TRUE);
  700.   }
  701.  
  702.   if (ReturnedSigs & N_ND->SerSig && N_ND->SerOK && N_ND->SerWaiting)
  703.   {
  704.     LIBSerWaitData();
  705.     N_ND->IBuffer=N_ND->SerBuffer;
  706.     N_ND->IBytes=N_ND->SerBytes;
  707.     return(TRUE);
  708.   }
  709.   return(FALSE);
  710. */
  711. }
  712.  
  713. ULONG SendDoorIOMessage(ULONG Status,UBYTE *Data,ULONG DataLength,ULONG Flags,UBYTE *OptionStr,ULONG Num1,ULONG Num2)
  714. {
  715.   ULONG retval=0;
  716.   struct DoorIOMsg *NewIOMsg=NULL;
  717.   if (NewIOMsg=(struct DoorIOMsg*)AllocVec(sizeof(struct DoorIOMsg),MEMF_PUBLIC))
  718.   {
  719.     NewIOMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  720.     NewIOMsg->message.mn_ReplyPort=C_DOOR.ReplyPort;
  721.     NewIOMsg->message.mn_Length=sizeof(struct DoorIOMsg);
  722.     NewIOMsg->MsgType=mtype_DOORIO;
  723.     NewIOMsg->Status=Status;
  724.     NewIOMsg->Data=Data;
  725.     NewIOMsg->DataLength=DataLength;
  726.     NewIOMsg->ReturnVal=0;
  727.     NewIOMsg->Flags=Flags;
  728.     NewIOMsg->OptionStr=OptionStr;
  729.     NewIOMsg->Num1=Num1;
  730.     NewIOMsg->Num2=Num2;
  731.     SendMessage((struct Message*)NewIOMsg,N_ND->PortName);
  732.     retval=NewIOMsg->ReturnVal;
  733.     FreeVec(NewIOMsg);
  734.   }
  735.   return(retval);
  736. }
  737.  
  738. ULONG QuickDoorIOMessage(ULONG Status,UBYTE *Data)
  739. {
  740.   // optimized send message for stuff that only uses Data and Datalen
  741.  
  742. //  return(SendDoorIOMessage(Status,Data,0,0,NULL,0,0));
  743.  
  744.   ULONG retval=0;
  745.   struct DoorIOMsg *NewIOMsg;
  746.   if (NewIOMsg=(struct DoorIOMsg*)AllocVec(sizeof(struct DoorIOMsg),MEMF_PUBLIC|MEMF_CLEAR))
  747.   {
  748.     NewIOMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  749.     NewIOMsg->message.mn_ReplyPort=C_DOOR.ReplyPort;
  750.     NewIOMsg->message.mn_Length=sizeof(struct DoorIOMsg);
  751.     NewIOMsg->MsgType=mtype_DOORIO;
  752.     NewIOMsg->Status=Status;
  753.     NewIOMsg->Data=Data;
  754.  
  755.     PutMsg(N_ND->NodePort,(struct Message*)NewIOMsg);
  756.  
  757.     if (1L << C_DOOR.ReplyPort->mp_SigBit==Wait(1L << C_DOOR.ReplyPort->mp_SigBit))
  758.     {
  759.       GetMsg(NewIOMsg->message.mn_ReplyPort);
  760.       retval=NewIOMsg->ReturnVal;
  761.     }
  762.     else retval=1L;
  763.  
  764.     FreeVec(NewIOMsg);
  765.     return(retval);
  766.  
  767.   }
  768.   else return(0);
  769. }
  770.  
  771. void __asm __saveds LIBDOOR_SysopText(register __a0 UBYTE *str)
  772. {
  773.   QuickDoorIOMessage(DOORIO_WRITECONSTR,str);
  774. }
  775.  
  776. void __asm __saveds LIBDOOR_WriteText(register __a0 UBYTE *str)
  777. {
  778.   QuickDoorIOMessage(DOORIO_WRITESTR,str);
  779. }
  780.  
  781. void __asm __saveds LIBDOOR_WriteSerText(register __a0 UBYTE *str)
  782. {
  783.   QuickDoorIOMessage(DOORIO_WRITESERSTR,str);
  784. }
  785.  
  786. ULONG __asm __saveds LIBDOOR_GetLine(register __d0 ULONG Flags, register __d1 char PasswordChar,register __d2 ULONG MaxLen,register __d3 ULONG Timeout,register __a0 UBYTE *PromptStr)
  787. {
  788.   char c=PasswordChar;
  789.  
  790.   return(SendDoorIOMessage(DOORIO_GETLINE,&c,1,Flags,PromptStr,MaxLen,Timeout));
  791. }
  792.  
  793. void __asm __saveds LIBDOOR_UpdateNodeStatus(register __d0 ULONG What)
  794. {
  795.   UBYTE *str=NULL;
  796.   UWORD X=0,MaxLen;
  797.   switch(What)
  798.   {
  799.     case UPD_NAME:
  800.       if (N_ND->User.Valid) str=N_ND->User.NormalData.Handle;
  801.       X=4;
  802.       MaxLen=MAX_NAME_LEN;
  803.       break;
  804.     case UPD_GROUP:
  805.       if (N_ND->User.Valid) str=N_ND->User.NormalData.Group;
  806.       X=164;
  807.       MaxLen=MAX_GROUP_LEN;
  808.       break;
  809.     case UPD_ACTION:
  810.       str=N_ND->Action;
  811.       X=324;
  812.       MaxLen=MAX_ACTION_LEN;
  813.       break;
  814.     case UPD_CPSBAUD:
  815.       if (!N_ND->TransferringFile) str=N_ND->ConnectBaud; // *C* add cps here
  816.       X=556;
  817.       MaxLen=MAX_CPSBAUD_LEN;
  818.       break;
  819.     default:
  820.       return;
  821.   }
  822.   // ok, have we got an option ?
  823.   // and a string to print ?
  824.   // AND if the window open ?
  825.   if ((X) && (str) && (!N_ND->NodeSettings.Iconified))
  826.   {
  827.     SetAPen(N_ND->NodeWnd->RPort,0L); // 0=grey
  828.     SetBPen(N_ND->NodeWnd->RPort,0); // grey!
  829.     RectFill(N_ND->NodeWnd->RPort, X+N_ND->NodeWnd->BorderLeft,15+N_ND->NodeWnd->BorderTop,X+N_ND->NodeWnd->BorderLeft+(8*MaxLen),15+N_ND->NodeWnd->BorderTop+9);
  830.  
  831.     if ((What == UPD_NAME) && (N_ND->NodeFlags & NFLG_PAGED))
  832.     {
  833.       SetAPen(N_ND->NodeWnd->RPort,2L); // white!
  834.     }
  835.     else
  836.     {
  837.       SetAPen(N_ND->NodeWnd->RPort,1L); // black!
  838.     }
  839.     Move(N_ND->NodeWnd->RPort,1+X+N_ND->NodeWnd->BorderLeft,8+14+N_ND->NodeWnd->BorderTop);  // 8 for text height, 13 for placement
  840.     Text(N_ND->NodeWnd->RPort,str,(strlen(str)>MaxLen) ? MaxLen : strlen(str));
  841.   }
  842. }
  843.  
  844. // spawn another system door, e.g. "FRONTEND"
  845.  
  846. void __asm __saveds LIBDOOR_SystemDoor(register __a0 UBYTE *doorname,register __a1 UBYTE *options)
  847. {
  848.   SendDoorIOMessage(DOORIO_SYSTEMDOOR,doorname,0,0,options,0,0);
  849. }
  850.  
  851. // spawn another user door, e.g. "FR W"
  852.  
  853. V_BOOL __asm __saveds LIBDOOR_UserDoor(register __a0 UBYTE *doorname,register __a1 UBYTE *options)
  854. {
  855.   return(SendDoorIOMessage(DOORIO_USERDOOR,doorname,0,0,options,0,0));
  856. }
  857.  
  858. V_BOOL __asm __saveds LIBDOOR_HangUp( void )
  859. {
  860.   return(SendDoorIOMessage(DOORIO_HANGUP,NULL,0,0,NULL,0,0));
  861. }
  862.  
  863. void __asm __saveds LIBDOOR_Return( register __a0 UBYTE *returnstring )
  864. {
  865.   strNcpy(N_ND->DoorReturn,returnstring,LEN_MAXDOORRETURN);
  866. }
  867.  
  868. V_BOOL __asm __saveds LIBDOOR_DisplayScreen( register __a0 UBYTE *screenname )
  869. {
  870.   return(SendDoorIOMessage(DOORIO_DISPLAYSCREEN,screenname,0,0,NULL,0,0));
  871. }
  872.  
  873. V_BOOL __asm __saveds LIBDOOR_DisplaySpecialScreen( register __a0 UBYTE *screenname )
  874. {
  875.   return(SendDoorIOMessage(DOORIO_DISPLAYSPECIALSCREEN,screenname,0,0,NULL,0,0));
  876. }
  877.  
  878.  
  879. V_BOOL __asm __saveds LIBDOOR_PausePrompt( register __a0 UBYTE *prompt )
  880. {
  881.   return(QuickDoorIOMessage(DOORIO_PAUSEPROMPT,prompt));
  882. }
  883.  
  884. void __asm __saveds LIBDOOR_Add_Last_Upload( register __a0 UBYTE *details )
  885. {
  886.   QuickDoorIOMessage(DOORIO_ADDLASTUPLOAD,details);
  887. }
  888.  
  889. void __asm __saveds LIBDOOR_Add_Last_Download( register __a0 UBYTE *details )
  890. {
  891.   QuickDoorIOMessage(DOORIO_ADDLASTDOWNLOAD,details);
  892. }
  893.  
  894.  
  895.  
  896. V_BOOL __asm __saveds LIBDOOR_ContinuePrompt( register __a0 UBYTE *prompt,register __d0 V_BIGNUM Flags )
  897. {
  898.   return(SendDoorIOMessage(DOORIO_CONTINUEPROMPT,prompt,0,Flags,NULL,0,0));
  899. }
  900.  
  901.  
  902. void __asm __saveds LIBDOOR_MenuPrompt(register __a0 char *promptstr,register __d0 char promptdefault)
  903. {
  904.   char options[2];
  905.   options[0]=promptdefault;
  906.   options[1]=0;
  907.  
  908.   SendDoorIOMessage(DOORIO_MENUPROMPT,promptstr,0,0,options,0,0);
  909. }
  910.  
  911. void __asm __saveds LIBDOOR_Continue( register __d0 V_BOOL Continue )
  912. {
  913.   N_ND->DoorContinue=Continue;
  914. }
  915.  
  916. V_BOOL __asm __saveds LIBValidConfNum(register __d0 V_BIGNUM ConfNum)
  917. {
  918.   // index from 1 (i.e. first conf = 1
  919.   return((V_BOOL)((ConfNum>0 && ConfNum <=BBSGlobal->Conferences) ? TRUE : FALSE));
  920. }
  921.  
  922. struct ConfData __asm __saveds *LIBFindConf( void )
  923. {
  924.   struct ConfData *Conf=NULL;
  925.   V_BIGNUM ConfNum;
  926.  
  927.  
  928.   if (N_ND->CurrentConf)
  929.   {
  930.     Conf=N_ND->CurrentConf;
  931.   }
  932.   else
  933.   {
  934.     if (N_ND->User.Valid)
  935.     {
  936.       if (ConfNum=N_ND->User.CallData.LastConf)
  937.       {
  938.         if (LIBValidConfNum(ConfNum))
  939.         {
  940.           Conf=(struct ConfData *)GetNode(BBSGlobal->ConfList,ConfNum-1);
  941.         }
  942.       }
  943.     }
  944.   }
  945.   return(Conf);
  946.  
  947. }
  948.  
  949.  
  950. void  __asm __saveds LIBLoadAccess( register __a0 char *filename, register __a1 struct AccessData *AD)
  951. {
  952.   struct CfgFileData *CfgFile;
  953.   V_BOOL acsdata;
  954.  
  955.   if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
  956.   {
  957.  
  958.     /* Main Options */
  959.  
  960.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DLFILES,OPT_SINGLE))
  961.       AD->Data[ACS_DLFILES]=acsdata ? 'Y' : 'N';
  962.  
  963.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ULFILES,OPT_SINGLE))
  964.       AD->Data[ACS_ULFILES]=acsdata ? 'Y' : 'N';
  965.  
  966.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SYSOPCOMMENT,OPT_SINGLE))
  967.       AD->Data[ACS_SYSOPCOMMENT]=acsdata ? 'Y' : 'N';
  968.  
  969.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_READMAIL,OPT_SINGLE))
  970.       AD->Data[ACS_READMAIL]=acsdata ? 'Y' : 'N';
  971.  
  972.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_WRITEMAIL,OPT_SINGLE))
  973.       AD->Data[ACS_WRITEMAIL]=acsdata ? 'Y' : 'N';
  974.  
  975.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SCANMAIL,OPT_SINGLE))
  976.       AD->Data[ACS_SCANMAIL]=acsdata ? 'Y' : 'N';
  977.  
  978.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWSTATUS,OPT_SINGLE))
  979.       AD->Data[ACS_ALLOWSTATUS]=acsdata ? 'Y' : 'N';
  980.  
  981.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEDIT,OPT_SINGLE))
  982.       AD->Data[ACS_ALLOWEDIT]=acsdata ? 'Y' : 'N';
  983.  
  984.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SCANFILES,OPT_SINGLE))
  985.       AD->Data[ACS_SCANFILES]=acsdata ? 'Y' : 'N';
  986.  
  987.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWVIEW,OPT_SINGLE))
  988.       AD->Data[ACS_ALLOWVIEW]=acsdata ? 'Y' : 'N';
  989.  
  990.  
  991.     /* Mail Options */
  992.  
  993.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEMAIL,OPT_SINGLE))
  994.       AD->Data[ACS_DELETEMAIL]=acsdata ? 'Y' : 'N';
  995.  
  996.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEGROUP,OPT_SINGLE))
  997.       AD->Data[ACS_DELETEGROUP]=acsdata ? 'Y' : 'N';
  998.  
  999.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEANYONE,OPT_SINGLE))
  1000.       AD->Data[ACS_DELETEANYONE]=acsdata ? 'Y' : 'N';
  1001.  
  1002.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWALL,OPT_SINGLE))
  1003.       AD->Data[ACS_ALLOWALL]=acsdata ? 'Y' : 'N';
  1004.  
  1005.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEVERYBODY,OPT_SINGLE))
  1006.       AD->Data[ACS_ALLOWEVERYBODY]=acsdata ? 'Y' : 'N';
  1007.  
  1008.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWMULTIPLE,OPT_SINGLE))
  1009.       AD->Data[ACS_ALLOWMULTIPLE]=acsdata ? 'Y' : 'N';
  1010.  
  1011.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ATTACHFILES,OPT_SINGLE))
  1012.       AD->Data[ACS_ATTACHFILES]=acsdata ? 'Y' : 'N';
  1013.  
  1014.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWMULTIFILES,OPT_SINGLE))
  1015.       AD->Data[ACS_ALLOWMULTIFILES]=acsdata ? 'Y' : 'N';
  1016.  
  1017.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWPRIVATEFILES,OPT_SINGLE))
  1018.       AD->Data[ACS_ALLOWPRIVATEFILES]=acsdata ? 'Y' : 'N';
  1019.  
  1020.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWALLFILES,OPT_SINGLE))
  1021.       AD->Data[ACS_ALLOWALLFILES]=acsdata ? 'Y' : 'N';
  1022.  
  1023.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEVERYONEFILES,OPT_SINGLE))
  1024.       AD->Data[ACS_ALLOWEVERYONEFILES]=acsdata ? 'Y' : 'N';
  1025.  
  1026.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_AUTOEXPIREMSG,OPT_SINGLE))
  1027.       AD->Data[ACS_AUTOEXPIREMSG]=acsdata ? 'Y' : 'N';
  1028.  
  1029.     /* W command settings */
  1030.  
  1031.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITHANDLE,OPT_SINGLE))
  1032.       AD->Data[ACS_EDITHANDLE]=acsdata ? 'Y' : 'N';
  1033.  
  1034.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITREALNAME,OPT_SINGLE))
  1035.       AD->Data[ACS_EDITREALNAME]=acsdata ? 'Y' : 'N';
  1036.  
  1037.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPASSWORD,OPT_SINGLE))
  1038.       AD->Data[ACS_EDITPASSWORD]=acsdata ? 'Y' : 'N';
  1039.  
  1040.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITGROUP,OPT_SINGLE))
  1041.       AD->Data[ACS_EDITGROUP]=acsdata ? 'Y' : 'N';
  1042.  
  1043.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITLOCATION,OPT_SINGLE))
  1044.       AD->Data[ACS_EDITLOCATION]=acsdata ? 'Y' : 'N';
  1045.  
  1046.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITCOUNTRY,OPT_SINGLE))
  1047.       AD->Data[ACS_EDITCOUNTRY]=acsdata ? 'Y' : 'N';
  1048.  
  1049.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITCOMPUTER,OPT_SINGLE))
  1050.       AD->Data[ACS_EDITCOMPUTER]=acsdata ? 'Y' : 'N';
  1051.  
  1052.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPHONENUMBER,OPT_SINGLE))
  1053.       AD->Data[ACS_EDITPHONENUMBER]=acsdata ? 'Y' : 'N';
  1054.  
  1055.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITSCREENTYPE,OPT_SINGLE))
  1056.       AD->Data[ACS_EDITSCREENTYPE]=acsdata ? 'Y' : 'N';
  1057.  
  1058.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITLINES,OPT_SINGLE))
  1059.       AD->Data[ACS_EDITLINES]=acsdata ? 'Y' : 'N';
  1060.  
  1061.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITEDITOR,OPT_SINGLE))
  1062.       AD->Data[ACS_EDITEDITOR]=acsdata ? 'Y' : 'N';
  1063.  
  1064.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPROTOCOL,OPT_SINGLE))
  1065.       AD->Data[ACS_EDITPROTOCOL]=acsdata ? 'Y' : 'N';
  1066.  
  1067.     /* ULIMITEDxxxx Settings */
  1068.  
  1069.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_UNLIMTIME,OPT_SINGLE))
  1070.       AD->Data[ACS_UNLIMTIME]=acsdata ? 'Y' : 'N';
  1071.  
  1072.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_UNLIMCALLS,OPT_SINGLE))
  1073.       AD->Data[ACS_UNLIMCALLS]=acsdata ? 'Y' : 'N';
  1074.  
  1075.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_UNLIMBYTES,OPT_SINGLE))
  1076.       AD->Data[ACS_UNLIMBYTES]=acsdata ? 'Y' : 'N';
  1077.  
  1078.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_UNLIMCHAT,OPT_SINGLE))
  1079.       AD->Data[ACS_UNLIMCHAT]=acsdata ? 'Y' : 'N';
  1080.  
  1081.  
  1082.  
  1083. /*  Spare ones
  1084.  
  1085.  
  1086.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_,OPT_SINGLE))
  1087.       AD->Data[ACS_]=acsdata ? 'Y' : 'N';
  1088.  
  1089.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_,OPT_SINGLE))
  1090.       AD->Data[ACS_]=acsdata ? 'Y' : 'N';
  1091. */
  1092.     HBBS_FlushConfig(CfgFile);
  1093.   }
  1094.  
  1095. }
  1096.  
  1097. char __asm __saveds *LIBHBBS_ModifyString(register __a0 char *str)
  1098. {
  1099.   char tmpstr[20];  // *D* Document! the {x} codes
  1100.  
  1101.   // Time Left
  1102.  
  1103.   sprintf(tmpstr,"%d",LIBHBBS_TimeLeft());
  1104.   replace(str,str,"{L}",tmpstr);
  1105.  
  1106.   // Time Online
  1107.  
  1108.   sprintf(tmpstr,"%d",LIBHBBS_TimeOnline());
  1109.   replace(str,str,"{O}",tmpstr);
  1110.  
  1111.   // System Name
  1112.  
  1113.   replace(str,str,"{S}",BBSGlobal->BBSName);
  1114.  
  1115.   // Conference Name
  1116.  
  1117.   if (N_ND->CurrentConf) replace(str,str,"{C}",N_ND->CurrentConf->node.ln_Name);
  1118.  
  1119.   // Actual Time Without Seconds
  1120.  
  1121.   HBBS_GetTime(tmpstr);
  1122.   tmpstr[5]=0;
  1123.   replace(str,str,"{T}",tmpstr);
  1124.  
  1125.   // Actual Time WITH seconds
  1126.  
  1127.   HBBS_GetTime(tmpstr);
  1128.   replace(str,str,"{TS}",tmpstr);
  1129.  
  1130.   // Actual Date
  1131.  
  1132.   HBBS_GetDate(tmpstr);
  1133.   replace(str,str,"{D}",tmpstr);
  1134.  
  1135.   // Credits Left (In Current Conference)
  1136.  
  1137.   replace(str,str,"{B}","<Creds>");
  1138.  
  1139.   // Ansi CSI
  1140.  
  1141.   replace(str,str,"{E}","\033[");
  1142.  
  1143.  
  1144.   if (N_ND->User.Valid)
  1145.   {
  1146.  
  1147.     // Users Handle
  1148.  
  1149.     replace(str,str,"{H}",N_ND->User.CallData.Handle);
  1150.  
  1151.     // Users Group
  1152.  
  1153.     replace(str,str,"{G}",N_ND->User.CallData.Group);
  1154.   }
  1155.  
  1156.   return(str);
  1157. }
  1158.  
  1159. V_BOOL __asm __saveds LIBHBBS_LoadConfAcs( register __a0 struct ConfAcsData *ConfAcs, register __a1 char *filename)
  1160. {
  1161.   V_BOOL retval=FALSE,error=FALSE;
  1162.  
  1163.   struct CfgFileData *CfgFile;
  1164.   int loop;
  1165.   struct BoolNode *tmpnode;
  1166.   V_BOOL TmpVal;
  1167.   char tmpstr[BIG_STR];
  1168.  
  1169.   if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
  1170.   {
  1171.     if (HBBS_GetSetting(CfgFile,(void *)&ConfAcs->Name,VTYPE_STRING,"Name",OPT_SINGLE))
  1172.     {
  1173.       TmpVal=FALSE;
  1174.       HBBS_GetSetting(CfgFile,(void *)&TmpVal,VTYPE_BOOL,"Default",OPT_SINGLE);
  1175.  
  1176.       // set allow/disallow conf access to whatever "default" is set to for all conferences
  1177.       for (loop=0;!error && loop<BBSGlobal->Conferences;loop++)
  1178.       {
  1179.         tmpnode=(struct BoolNode*)GetNode(ConfAcs->Access,loop);
  1180.         tmpnode->Boolean=TmpVal;
  1181.       }
  1182.  
  1183.       // then make this value the opposite for all "Override_<confnum>=YES"'s
  1184.       for (loop=0;!error && loop<BBSGlobal->Conferences;loop++)
  1185.       {
  1186.         sprintf(tmpstr,"Override_%d",loop+1);
  1187.         if (HBBS_GetSetting(CfgFile,(void *)&TmpVal,VTYPE_BOOL,tmpstr,OPT_SINGLE) && TmpVal==TRUE)
  1188.         {
  1189.           tmpnode=(struct BoolNode*)GetNode(ConfAcs->Access,loop);
  1190.           tmpnode->Boolean=!tmpnode->Boolean;
  1191.         }
  1192.       }
  1193.  
  1194.       // then do the same thing for SeeDefault and all See_<confnum>'s
  1195.       TmpVal=FALSE;
  1196.       HBBS_GetSetting(CfgFile,(void *)&TmpVal,VTYPE_BOOL,"SeeDefault",OPT_SINGLE);
  1197.  
  1198.       for (loop=0;!error && loop<BBSGlobal->Conferences;loop++)
  1199.       {
  1200.         tmpnode=(struct BoolNode*)GetNode(ConfAcs->See,loop);
  1201.         tmpnode->Boolean=TmpVal;
  1202.       }
  1203.  
  1204.       for (loop=0;!error && loop<BBSGlobal->Conferences;loop++)
  1205.       {
  1206.         sprintf(tmpstr,"SeeOverride_%d",loop+1);
  1207.         if (HBBS_GetSetting(CfgFile,(void *)&TmpVal,VTYPE_BOOL,tmpstr,OPT_SINGLE) && TmpVal==TRUE)
  1208.         {
  1209.           tmpnode=(struct BoolNode*)GetNode(ConfAcs->See,loop);
  1210.           tmpnode->Boolean=!tmpnode->Boolean;
  1211.         }
  1212.       }
  1213.       retval=TRUE;
  1214.     }
  1215.     HBBS_FlushConfig(CfgFile);
  1216.   }
  1217.   return(retval);
  1218. }
  1219.  
  1220.  
  1221. void __asm __saveds LIBHBBS_SetAccess( void )
  1222. {
  1223.   char tmpfilename[BIG_STR];
  1224.   V_BIGNUM loop;
  1225.  
  1226.   // Clear out the access
  1227.  
  1228.   for (loop=0;loop<MAX_ACCESSSETTINGS;loop++)
  1229.   {
  1230.     N_ND->User.Acs.Data[loop]='N';
  1231.   }
  1232.  
  1233.   if (N_ND->User.Valid)
  1234.   {
  1235.     N_ND->User.Acs.AccessLevel=N_ND->User.CallData.Access;
  1236.  
  1237.     LIBLoadAccess("HBBS:Access/Levels/Level_Global",&N_ND->User.Acs);
  1238.  
  1239.     sprintf(tmpfilename,"HBBS:Access/Levels/Level_%d",N_ND->User.Acs.AccessLevel);
  1240.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1241.  
  1242.     sprintf(tmpfilename,"%sAccess/Level_%d",N_ND->NodeLocation,N_ND->User.Acs.AccessLevel);
  1243.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1244.  
  1245.     if (N_ND->CurrentConf)
  1246.     {
  1247.       sprintf(tmpfilename,"%sAccess/Level_%d",N_ND->CurrentConf->ConfPath,N_ND->User.Acs.AccessLevel);
  1248.       LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1249.     }
  1250.  
  1251.     sprintf(tmpfilename,"HBBS:Access/Users/%s",N_ND->User.CallData.Handle);
  1252.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1253.  
  1254.     sprintf(tmpfilename,"HBBS:System/Data/ConfAcs/%s.CFG",N_ND->User.CallData.ConfAcsDataFile);
  1255.     if (!LIBHBBS_LoadConfAcs(&N_ND->User.ConfAcs,tmpfilename))
  1256.     {
  1257.       HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_ERROR_OPENING,tmpfilename,TYPE_WARNING);
  1258.     }
  1259.   }
  1260. }
  1261.  
  1262. V_BOOL __asm __saveds LIBHBBS_CheckAccess(register __d0 ULONG AccessOption)
  1263. {
  1264.   if ((N_ND->User.Valid) && (N_ND->User.Acs.Data[AccessOption]=='Y')) return(TRUE); else return(FALSE);
  1265. }
  1266.  
  1267. void __asm __saveds LIBHBBS_AddToCallersLog(register __a0 UBYTE *String)
  1268. {
  1269.   UBYTE tmpstr[BIG_STR];
  1270.  
  1271.   if (N_ND->NodeSettings.CallersLogFile)
  1272.   {
  1273.  
  1274.     HBBS_GetDate(tmpstr);
  1275.     strcat(tmpstr," ");
  1276.     HBBS_GetTime(tmpstr+strlen(tmpstr));
  1277.     strcat(tmpstr," ");
  1278.     strcat(tmpstr,String);
  1279.     strcat(tmpstr,"\n");
  1280.  
  1281.     HBBS_AppendStrToFile(N_ND->NodeSettings.CallersLogFile,tmpstr);
  1282.   }
  1283. }
  1284.  
  1285.  
  1286. struct TaggedFile __asm __saveds *LIBHBBS_FindTag(register __a0 UBYTE *FileName,register __d0 BOOL MatchALL)
  1287. {
  1288.   struct TaggedFile *Tag=NULL,*retval=NULL;
  1289.  
  1290.   if (N_ND->TaggedFiles)
  1291.   {
  1292.     for (Tag=(struct TaggedFile*)N_ND->TaggedFileList->lh_Head;!retval && Tag->node.ln_Succ;Tag=(struct TaggedFile *)Tag->node.ln_Succ)
  1293.     {
  1294.       if (MatchALL)
  1295.       {
  1296.         if (stricmp(FileName,Tag->node.ln_Name)==0)
  1297.         {
  1298.           retval=Tag;
  1299.         }
  1300.       }
  1301.       else
  1302.       {
  1303.         if (stricmp(FilePart(FileName),FilePart(Tag->node.ln_Name))==0)
  1304.         {
  1305.           retval=Tag;
  1306.         }
  1307.       }
  1308.     }
  1309.   }
  1310.   return(retval);
  1311. }
  1312.  
  1313.  
  1314. void __asm __saveds LIBHBBS_SetBBSCols( void )
  1315. {
  1316.   struct CfgFileData *CfgFile;
  1317.   char filename[1024],*bbscolsfile="BBSColours.CFG";
  1318.  
  1319.   BOOL foundfile=FALSE;
  1320.   BYTE triedall=3;
  1321.  
  1322.   FreeAndSet(&N_ND->BBSCols->MenuTextANSI,"");
  1323.   FreeAndSet(&N_ND->BBSCols->MenuOpenBracket,"[");
  1324.   FreeAndSet(&N_ND->BBSCols->MenuCloseBracket,"]");
  1325.   FreeAndSet(&N_ND->BBSCols->MenuHighlightANSI,"");
  1326.   FreeAndSet(&N_ND->BBSCols->MenuDefaultOptANSI,"");
  1327.   FreeAndSet(&N_ND->BBSCols->MenuPromptANSI,":");
  1328.  
  1329.   do
  1330.   {
  1331.     triedall--;
  1332.     switch (triedall)
  1333.     {
  1334.       case 2:
  1335.         if (N_ND->CurrentConf)
  1336.         {
  1337.           strcpy(filename,N_ND->CurrentConf->ConfPath);
  1338.           strcat(filename,bbscolsfile);
  1339.         } else filename[0]=0;
  1340.         break;
  1341.       case 1:
  1342.         strcpy(filename,N_ND->NodeLocation);
  1343.         strcat(filename,bbscolsfile);
  1344.         break;
  1345.       case 0:
  1346.         strcpy(filename,"HBBS:System/Data/");
  1347.         strcat(filename,bbscolsfile);
  1348.         break;
  1349.     }
  1350.     if (filename[0])
  1351.     {
  1352.       if (CfgFile=HBBS_LoadConfig(filename,LCFG_NOSTRIPCOMMENTS))
  1353.       {
  1354.         foundfile=TRUE;
  1355.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuTextANSI,VTYPE_STRING,"MenuTextANSI",OPT_SINGLE)             ;
  1356.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuOpenBracket,VTYPE_STRING,"MenuOpenBracket",OPT_SINGLE)       ;
  1357.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuCloseBracket,VTYPE_STRING,"MenuCloseBracket",OPT_SINGLE)     ;
  1358.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuHighlightANSI,VTYPE_STRING,"MenuHighlightANSI",OPT_SINGLE)   ;
  1359.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuDefaultOptANSI,VTYPE_STRING,"MenuDefaultOptANSI",OPT_SINGLE) ;
  1360.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuPromptANSI,VTYPE_STRING,"MenuPromptANSI",OPT_SINGLE)         ;
  1361.  
  1362.         HBBS_FlushConfig(CfgFile);
  1363.       }
  1364.     }
  1365.   } while ((!foundfile) && (triedall>0));
  1366. }
  1367.  
  1368.  
  1369. V_BOOL __asm __saveds LIBDOOR_CheckRaw(register __d0 ULONG Flags)
  1370. {
  1371.   return(SendDoorIOMessage(DOORIO_CHECKRAW,NULL,0,Flags,NULL,0,0));
  1372. }
  1373.  
  1374.  
  1375. LONG __asm __saveds LIBHBBS_TimeLeft( void )
  1376. {
  1377.   // return 0 if time limit is disabled, or the amount of time left..
  1378.   // therefore: only log people off if this returns <0, but ideally check for ACS_UNLIMTIME too...
  1379.   return((N_ND->User.Acs.Data[ACS_UNLIMTIME]=='Y') ? 0 : ((LONG)((N_ND->User.CallData.TimeAllowed+N_ND->User.CallData.ExtraTimeLimit)-N_ND->User.CallData.TimeUsed-LIBHBBS_TimeOnline())));
  1380.  
  1381. }
  1382.  
  1383. LONG __asm __saveds LIBHBBS_TimeOnline( void )
  1384. {
  1385.   LONG tdiff;
  1386.     // current time, - time logged on (secs) * 60 = mins on-line
  1387.   time(&tdiff);
  1388.  
  1389.   return((tdiff-N_ND->User.CallData.LastCalledDate) / 60);
  1390. }
  1391.  
  1392. void __asm __saveds LIBDOOR_Goodbye( void )
  1393. {
  1394.   // Perform all actions required for a sucessful logoff..
  1395.   // (see Logout door for an example..)
  1396.  
  1397.   N_ND->OnlineStatus=OS_OFFLINE;
  1398.  
  1399.   // lostcarrier flag is set by default when a user has a successful login,
  1400.   // so we must UNset it!
  1401.   N_ND->Actions[ACTN_CARRIERLOST]=ACTC_NONE;
  1402. }
  1403.  
  1404. BOOL __asm __saveds LIBHBBS_AllowConfAccess(register __d0 V_BIGNUM confnum,register __a0 struct UserData *User)
  1405. {
  1406.   // confnum starts at 1.
  1407.  
  1408.   struct ConfData *tmpconf;
  1409.   struct BoolNode *boolnode;
  1410.  
  1411.   char tmpfilename[BIG_STR];
  1412.   struct UserData *CheckUser;
  1413.   struct ConfAcsData *CheckConfAcs;
  1414.   struct ConfAcsData ConfAcsDat;
  1415.   V_BOOL error=FALSE;
  1416.   BOOL retval=FALSE;
  1417.   int loop;
  1418.   struct Node *node;
  1419.  
  1420.  
  1421.   if (!error)
  1422.   {
  1423.     if (User==NULL)
  1424.     {
  1425.       CheckUser=&N_ND->User.CallData;
  1426.       CheckConfAcs=&N_ND->User.ConfAcs;
  1427.     }
  1428.     else
  1429.     {
  1430.       CheckUser=User;
  1431.  
  1432.       if (ConfAcsDat.See=HBBS_CreateList())
  1433.       {
  1434.         for (loop=0;(!error) && (loop<BBSGlobal->Conferences);loop++)
  1435.         {
  1436.           if (node=AllocVec(sizeof(struct BoolNode),MEMF_CLEAR|MEMF_PUBLIC))
  1437.           {
  1438.             AddTail(ConfAcsDat.See,node);
  1439.           }
  1440.           else error=TRUE;
  1441.         }
  1442.       } else error=TRUE;
  1443.  
  1444.       if (ConfAcsDat.Access=HBBS_CreateList())
  1445.       {
  1446.         for (loop=0;(!error) && (loop<BBSGlobal->Conferences);loop++)
  1447.         {
  1448.           if (node=AllocVec(sizeof(struct BoolNode),MEMF_CLEAR|MEMF_PUBLIC))
  1449.           {
  1450.             AddTail(ConfAcsDat.Access,node);
  1451.           }
  1452.           else error=TRUE;
  1453.         }
  1454.       } else error=TRUE;
  1455.  
  1456.       if (error)
  1457.       {
  1458.         confnum=0; // forces a skip of the next section
  1459.       }
  1460.       else
  1461.       {
  1462.         sprintf(tmpfilename,"HBBS:System/Data/ConfAcs/%s.CFG",CheckUser->ConfAcsDataFile);
  1463.         if (LIBHBBS_LoadConfAcs(&ConfAcsDat,tmpfilename))
  1464.         {
  1465.           CheckConfAcs=&ConfAcsDat;
  1466.         }
  1467.         else
  1468.         {
  1469.           confnum=0; //to force a FALSE return...
  1470.         }
  1471.       }
  1472.     }
  1473.  
  1474.  
  1475.     if (confnum>0 && confnum<=BBSGlobal->Conferences)
  1476.     {
  1477.       tmpconf=(struct ConfData *)GetNode(BBSGlobal->ConfList,confnum-1);
  1478.  
  1479.       // access level required to enter conference greater than users access level ?
  1480.       if (!(tmpconf->ConfAccess > CheckUser->Access))
  1481.       {
  1482.         boolnode=(struct BoolNode *)GetNode(CheckConfAcs->Access,confnum-1);
  1483.         retval=(BOOL)boolnode->Boolean;
  1484.       }
  1485.     }
  1486.   }
  1487.  
  1488.   if (User)
  1489.   {
  1490.     FreeStrList(ConfAcsDat.See);    // frees the list and it's nodes, this is ok even on a list of boolnodes
  1491.     FreeStrList(ConfAcsDat.Access); // because no strings are allocated and everything uses alloc/freevec()
  1492.   }
  1493.  
  1494.   return(retval);
  1495. }
  1496.  
  1497. void __asm __saveds LIBHBBS_SetBBSStrings( void )
  1498. {
  1499.   struct CfgFileData *CfgFile;
  1500.   char filename[1024],*bbsstringsfile="BBSStrings.CFG";
  1501.  
  1502.   BOOL foundfile=FALSE;
  1503.   BYTE triedall=3;
  1504.  
  1505.   FreeAndSet(&N_ND->BBSStrings->PausePrompt,"Press [Return] to continue!");
  1506.  
  1507.   do
  1508.   {
  1509.     triedall--;
  1510.     switch (triedall)
  1511.     {
  1512.       case 2:
  1513.         if (N_ND->CurrentConf)
  1514.         {
  1515.           strcpy(filename,N_ND->CurrentConf->ConfPath);
  1516.           strcat(filename,bbsstringsfile);
  1517.         } else filename[0]=0;
  1518.         break;
  1519.       case 1:
  1520.         strcpy(filename,N_ND->NodeLocation);
  1521.         strcat(filename,bbsstringsfile);
  1522.         break;
  1523.       case 0:
  1524.         strcpy(filename,"HBBS:System/Data/");
  1525.         strcat(filename,bbsstringsfile);
  1526.         break;
  1527.     }
  1528.     if (filename[0])
  1529.     {
  1530.       if (CfgFile=HBBS_LoadConfig(filename,LCFG_NOSTRIPCOMMENTS))
  1531.       {
  1532.         foundfile=TRUE;
  1533.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSStrings->PausePrompt,VTYPE_STRING,"PausePrompt",OPT_SINGLE)         ;
  1534.  
  1535.         HBBS_FlushConfig(CfgFile);
  1536.       }
  1537.     }
  1538.   } while ((!foundfile) && (triedall>0));
  1539. }
  1540.  
  1541. // DO NOT CALL FROM A DOOR.  as your door will get the signals, not the NODE program!
  1542.  
  1543. void __asm __saveds LIBHBBS_CleanupNodeConsoleWin( void )
  1544. {
  1545.   // do everything in reverse order..
  1546.  
  1547.   if (N_ND->ConScr)
  1548.   {
  1549.     if (N_ND->ConWin)
  1550.     {
  1551.       if (!N_ND->NodeSettings.UseOwnScreen) // only save settings for window rather than a screen...
  1552.       {
  1553.         N_ND->ConX=N_ND->ConWin->LeftEdge;
  1554.         N_ND->ConY=N_ND->ConWin->TopEdge;
  1555.         N_ND->ConW=N_ND->ConWin->Width;
  1556.         N_ND->ConH=N_ND->ConWin->Height;
  1557.       }
  1558.       if (N_ND->ConBuffer)
  1559.       {
  1560.         if (N_ND->ConRPort)
  1561.         {
  1562.           if (N_ND->ConWPort)
  1563.           {
  1564.             if (N_ND->ConWrite)
  1565.             {
  1566.               if (N_ND->ConRead)
  1567.               {
  1568.                 // remove any pending requests..
  1569.                 if (N_ND->ConWaiting) LIBAbortConRead();
  1570.                 CloseDevice((struct IORequest*)N_ND->ConWrite);
  1571.                 DeleteExtIO((struct IORequest*)N_ND->ConRead);
  1572.               }
  1573.               DeleteExtIO((struct IORequest*)N_ND->ConWrite);
  1574.             }
  1575.             DeletePort(N_ND->ConWPort);
  1576.           }
  1577.           DeletePort(N_ND->ConRPort);
  1578.         }
  1579.         FreeVec(N_ND->ConBuffer);
  1580.       }
  1581.       CloseWindow(N_ND->ConWin);
  1582.     }
  1583.     if (N_ND->NodeSettings.UseOwnScreen)
  1584.     {
  1585.  
  1586.       while (!CloseScreen(N_ND->ConScr)); // *C* possible hang... changeme!
  1587.     }
  1588.     else
  1589.     {
  1590.       UnlockPubScreen(NULL,N_ND->ConScr);
  1591.       N_ND->ConScr=NULL;
  1592.     }
  1593.   }
  1594.   N_ND->ConWin=NULL;
  1595.   N_ND->ConScr=NULL;
  1596.   N_ND->ConOK=FALSE;
  1597.   ScreenToFront(BBSGlobal->ScreenInfo.Scr); // put Main screen to front..
  1598. }
  1599.  
  1600. void __asm __saveds LIBHBBS_SetWatchTitles( void )
  1601. {
  1602.   // change the title of the window evenif the y are not open
  1603.   // so that when you do open then they are correct.
  1604.  
  1605.  
  1606.   sprintf(N_ND->ConWinTitle,"Node %d ",N_ND->NodeNum);
  1607.  
  1608.   if (N_ND->User.Valid)
  1609.   {
  1610.  
  1611.     sprintf(&N_ND->ConWinTitle[strlen(N_ND->ConWinTitle)],"%s %s (%s)",N_ND->User.CallData.Handle,N_ND->User.CallData.Group,N_ND->ConnectBaud);
  1612.   }
  1613.  
  1614.   // update then if they are open
  1615.  
  1616.   if (N_ND->ConOK) SetWindowTitles(N_ND->ConWin,N_ND->ConWinTitle,N_ND->ConWinTitle); // set screen title
  1617. }
  1618.  
  1619. // DO NOT CALL FROM A DOOR.  as your door will get the signals, not the NODE program!
  1620.  
  1621. V_BOOL __asm __saveds LIBHBBS_OpenNodeConsoleWin( void )
  1622. {
  1623.   N_ND->ConOK=FALSE;
  1624.   sprintf(N_ND->ConScreenName,"NodeWatch_%d",N_ND->NodeNum);
  1625.   if (N_ND->NodeSettings.UseOwnScreen)
  1626.   {
  1627.     if (N_ND->ConScr=OpenScreenTags(NULL,
  1628.                                 SA_Colors,  N_ND->ScrCols,
  1629.                                 SA_Pens,  N_ND->DriPens,
  1630.                                 SA_Depth,N_ND->NodeSettings.ScrDepth,
  1631.                                 SA_Left,0,
  1632.                                 SA_Top,0,
  1633.                                 SA_Width,N_ND->NodeSettings.ScrWidth,
  1634.                                 SA_Height,N_ND->NodeSettings.ScrHeight,
  1635.                                 SA_DisplayID,N_ND->NodeSettings.ScrModeID,
  1636.                                 SA_Overscan,1,
  1637.                                 SA_AutoScroll,1,
  1638.                                 SA_Font, N_ND->HBBSTextAttr,
  1639. //                                SA_SysFont, 0,
  1640.                                 SA_PubName,N_ND->ConScreenName,
  1641.                                 TAG_DONE))
  1642.     {
  1643.       PubScreenStatus(N_ND->ConScr,0);
  1644.     }
  1645.  
  1646.   }
  1647.   else
  1648.   {
  1649.     N_ND->ConScr=LockPubScreen(BBSGlobal->ScreenInfo.PubScreenName);
  1650.   }
  1651.  
  1652.   if (N_ND->ConScr)
  1653.   {
  1654.     if (N_ND->ConWin=OpenWindowTags(NULL,
  1655.                                     WA_CustomScreen,N_ND->ConScr,
  1656.                                     WA_Left,N_ND->NodeSettings.UseOwnScreen ? 0 : N_ND->ConX,
  1657.                                     WA_Top,N_ND->NodeSettings.UseOwnScreen ? 11 : N_ND->ConY,
  1658.                                     WA_Width,N_ND->NodeSettings.UseOwnScreen ? N_ND->NodeSettings.ScrWidth : N_ND->ConW,
  1659.                                     WA_Height,N_ND->NodeSettings.UseOwnScreen ? N_ND->NodeSettings.ScrHeight-11 : N_ND->ConH,
  1660.                                     WA_AutoAdjust,TRUE,
  1661.                                     WA_MinWidth,200,
  1662.                                     WA_MinHeight,50,
  1663.                                     WA_MaxHeight,65534,
  1664.                                     WA_MaxWidth,65534,
  1665.                                     WA_BlockPen,7,
  1666.                                     WA_DetailPen,0,
  1667.                                     WA_Flags,N_ND->NodeSettings.UseOwnScreen ? WFLG_BORDERLESS|WFLG_BACKDROP|WFLG_ACTIVATE : WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_SIZEGADGET|WFLG_ACTIVATE,
  1668.                                     WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE,
  1669.                                     WA_SmartRefresh,TRUE,
  1670.                                     TAG_DONE))
  1671.     {
  1672.       SetFont(N_ND->ConWin->RPort,N_ND->HBBSFont);
  1673.       if (N_ND->ConBuffer=AllocVec(DEF_CONBUFLEN,MEMF_PUBLIC))
  1674.       {
  1675.         N_ND->ConBufferLen=DEF_CONBUFLEN;
  1676.         if (N_ND->ConRPort=CreateMsgPort())
  1677.         {
  1678.           if (N_ND->ConWPort=CreateMsgPort())
  1679.           {
  1680.             if (N_ND->ConWrite = (struct IOStdReq *) CreateExtIO(N_ND->ConWPort,(LONG)sizeof(struct IOStdReq)))
  1681.             {
  1682.               if (N_ND->ConRead = (struct IOStdReq *) CreateExtIO(N_ND->ConRPort,(LONG)sizeof(struct IOStdReq)))
  1683.               {
  1684.                 N_ND->ConWrite->io_Data = (APTR) N_ND->ConWin;
  1685.                 N_ND->ConWrite->io_Length = sizeof(struct Window);
  1686.  
  1687.                 if (!(OpenDevice("console.device", CONU_SNIPMAP, (struct IORequest*)N_ND->ConWrite, 0)))
  1688.                 {
  1689.                   N_ND->ConRead->io_Device = N_ND->ConWrite->io_Device;
  1690.                   N_ND->ConRead->io_Unit   = N_ND->ConWrite->io_Unit;
  1691.                   N_ND->ConWaiting=FALSE;
  1692.                   N_ND->ConOK=TRUE;
  1693.                   LIBHBBS_SetWatchTitles();
  1694.                   ScreenToFront(N_ND->ConScr); // put Console Screen to front..
  1695.                   return(TRUE);
  1696.                 }
  1697.               }
  1698.             }
  1699.           }
  1700.         }
  1701.       }
  1702.     }
  1703.   }
  1704.   LIBHBBS_CleanupNodeConsoleWin();
  1705.  
  1706.   return(FALSE);
  1707. }
  1708.  
  1709. // DO NOT CALL FROM A DOOR.  as your door will get the signals, not the NODE program!
  1710.  
  1711. void __asm __saveds LIBHBBS_ChangeConsoleMode( register __d0 short Mode )
  1712. {
  1713.   if (Mode==2)
  1714.   {
  1715.     if (N_ND->NodeSettings.UseOwnScreen) Mode=1; else Mode=0;
  1716.   }
  1717.   if (Mode==0) // use screen
  1718.   {
  1719.     if (!N_ND->NodeSettings.UseOwnScreen)
  1720.     {
  1721.       if (N_ND->ConOK) LIBHBBS_CleanupNodeConsoleWin();
  1722.       // don't change the setting until the console window
  1723.       // and or screen has been closed otherwise it will try to close
  1724.       // the screen rather than unlocking it :-)
  1725.       N_ND->NodeSettings.UseOwnScreen=TRUE;
  1726.       LIBHBBS_OpenNodeConsoleWin();
  1727.     }
  1728.   }
  1729.   if (Mode==1) // use window
  1730.   {
  1731.     if (N_ND->NodeSettings.UseOwnScreen)
  1732.     {
  1733.       if (N_ND->ConOK) LIBHBBS_CleanupNodeConsoleWin();
  1734.       N_ND->NodeSettings.UseOwnScreen=FALSE;
  1735.       LIBHBBS_OpenNodeConsoleWin();
  1736.     }
  1737.   }
  1738. }
  1739.  
  1740.  
  1741. void __asm __saveds LIBDOOR_ChangeConsoleMode( register __d0 short Mode )
  1742. {
  1743.   SendDoorIOMessage(DOORIO_CHANGECONSOLEMODE,NULL,0,NULL,NULL,Mode,0);
  1744. }
  1745.